#ifndef VMXML_H
#define VMXML_H

#ifdef __cplusplus
extern "C" {
#endif

#include "vmsys.h"

/*************************************************************/
/* Main data structures & types */

/**
 *	DOCTYPE tag start handler, be called when the parser begin to parse a DOCTYPE tag.
 *
 *    @param data				Reserved
 *    @param doctypeName		Document type name
 *    @param sysid				Array of system id
 *    @param pubid				Array of public id
 *    @param internal_subset	Internal subset (always 0)
 *    @param error 				Error code, type of VM_XML_ERROR_ENUM
 *
 *	@return					void

****************************************************************
DOCTYPE Examples:

-CSDN
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
doctypeName: html
pubid:
	"-//W3C//DTD XHTML 1.0 Transitional//EN" 
	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
	
-Gmail
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
doctypeName: HTML
pubid:
	"-//W3C//DTD HTML 4.01 Transitional//EN" 
	"http://www.w3.org/TR/html4/loose.dtd"

-Google Calendar
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" 
"http://www.w3.org/TR/html4/strict.dtd">
doctypeName: HTML
pubid:
	"-//W3C//DTD HTML 4.01//EN" 
	"http://www.w3.org/TR/html4/strict.dtd"

<!DOCTYPE note SYSTEM "Note.dtd">
doctypeName: note
sysid:
	"Note.dtd"
****************************************************************

 */
typedef void (*XML_start_doctype_hdlr) (
	void *data, 
	const VMCHAR *doctypeName,  
	const VMCHAR **sysid, 
	const VMCHAR **pubid,
	VMINT internal_subset,
	VMINT error);

/**
 *	DOCTYPE tag end handler, be called when the parser finish parse a DOCTYPE tag.
 *
 *    @param data				Reserved
 *    @param error 				Error code, type of VM_XML_ERROR_ENUM
 *
 *	@return					void
 */
typedef void (*XML_end_doctype_hdlr) (
	void *data, 
	VMINT error);

/**
 *	DOCTYPE tag end handler, be called when the parser finish parse a DOCTYPE tag.
 *
 *    @param data				Reserved
 *    @param el				Element name
 *    @param attr 				Attribution list
 *    @param error 				Error code, type of VM_XML_ERROR_ENUM
 *
 *	@return					void
 */
typedef void (*XML_start_elem_hdlr) (
	void *data,
	const VMCHAR *el,
	const VMCHAR **attr,
	VMINT error);

/**
 *	Element tag end handler, be called when the parser finish parse an element.
 *
 *    @param data				Reserved
 *    @param el				Element name
 *    @param error 				Error code, type of VM_XML_ERROR_ENUM
 *
 *	@return					void
 */
typedef void (*XML_end_elem_hdlr) (
	void *data, 
	const VMCHAR *el, 
	VMINT error);

/**
 *	Data handler, be called when the parser parse the data in an element.
 *
 *    @param data				Reserved
 *    @param el				Element name
 *    @param data 				Data
 *    @param len				Length
 *    @param error 				Error code, type of VM_XML_ERROR_ENUM
 *
 *	@return					void
 */
typedef void (*XML_data_hdlr) (
	void *resv,
	const VMCHAR *el,
	const VMCHAR *data,
	VMINT len,
	VMINT error);

/**
 * Error code of parse result.
 */
typedef enum
{
    VM_XML_RESULT_FILE_NOT_FOUND = -4,	/* the file isn't found */
    VM_XML_RESULT_OUT_OF_MEMORY = -3,		/* the memory isn't enough*/
    VM_XML_RESULT_ENCODING_ERROR = -2,	/* the char encoding error */
    VM_XML_RESULT_FAIL = -1,				/* fail to parse xml */
    VM_XML_RESULT_OK = 0					/* parsing xml succed */
} VM_XML_RESULT_ENUM;

/**
 * Error code while parsing.
 */
typedef enum
{
    VM_XML_NO_ERROR,									/* no error */
    VM_XML_ERROR_MISMATCH_TAG,						/* error string: end tag name */
    VM_XML_ERROR_MISMATCH_DOCTYPENAME_ROOTNAME,	/* error string: root element name */
    VM_XML_ERROR_INVALID_ATTRIBUTE,					/* error string: attribute name */
    VM_XML_ERROR_DUPLICATE_ATTRIBUTE,				/* error string: attribute name */
    VM_XML_ERROR_ENTITY_DEFINITION,					/* error string: entity name */
    VM_XML_ERROR_UNDEFINED_ENTITY               			/* error string: entity name */
} VM_XML_ERROR_ENUM;

/**
 * Struct of parser, with all tag handlers.
 */
typedef struct _VM_XML_PARSER_STRUCT 
{
	XML_start_doctype_hdlr start_doctype_hdlr;	/* function pointer provided by app */
	XML_end_doctype_hdlr end_doctype_hdlr;	/* function pointer provided by app */
	XML_start_elem_hdlr start_elem_hdlr;		/* function pointer provided by app */
	XML_end_elem_hdlr end_elem_hdlr;			/* function pointer provided by app */
	XML_data_hdlr data_hdlr;					/* function pointer provided by app */
} VM_XML_PARSER_STRUCT;

/*************************************************************/
/** Main APIs */
/**
 * Initialize a new XML parser. The default handlers will be assigned.
 *
 * @param parser		Global parser struct
 *
 * @return			Succeed:VM_XML_RESULT_FAIL; Failed:VM_XML_RESULT_OK
 */
VMINT vm_xml_new_parser(VM_XML_PARSER_STRUCT *parser);

/**
 * Set the DOCTYPE tag handler for a XML parser.
 *
 * @param parser		Global parser struct
 * @param start_hdlr	Function handler to handle start doc data
 * @param end_hdlr	Function handler to handle end doc data
 *
 * @return			void
 */
void vm_xml_set_doctype_handlers(
	VM_XML_PARSER_STRUCT *parser,
	XML_start_doctype_hdlr start_hdlr,
	XML_end_doctype_hdlr end_hdlr);

/**
 * Set the element tag handler for a XML parser.
 *
 * @param parser		Global parser struct
 * @param start_hdlr	Function handler to handle start element data
 * @param end_hdlr	Function handler to handle end element data
 *
 * @return			void
 */
void vm_xml_set_element_handlers(
	VM_XML_PARSER_STRUCT *parser,
	XML_start_elem_hdlr start_hdlr,
	XML_end_elem_hdlr end_hdlr);

/**
 * Set the data handler for a XML parser.
 *
 * @param parser		Global parser struct
 * @param elem_hdlr	Function handler to handle data
 *
 * @return			void
 */
void vm_xml_set_data_handler(
	VM_XML_PARSER_STRUCT *parser, 
	XML_data_hdlr data_hdlr);

/**
 * Start parsing a XML parser.
 *
 * @param parser		Global parser struct
 * @param xmlsource	Xml source, maybe file, maybe buffer.
 * @param length		"0" file; ">0" the length of buffer
 *
 * @return			0 succeed; <0 errors
 */
VMINT vm_xml_parse(
	VM_XML_PARSER_STRUCT *parser,
	const VMCHAR *xmlsource,
	VMINT length);

/**
 * Get the error string.
 *
 * @param parser		Global parser struct
 *
 * @return			error string
 */
VMCHAR* vm_xml_get_error(void);


#ifdef __cplusplus
}
#endif

#endif
